/*
 * @Author: shenya shenya0203@163.com
 * @Date: 2024-03-06 10:23:35
 * @LastEditors: shenya shenya0203@163.com
 * @LastEditTime: 2024-04-24 10:16:19
 * @FilePath: /code/src/json_data.c
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cJSON.h"
#include "log.h"
#include "json_data.h"
#include "udp_server.h"
#include "mqtt_cli.h"
#include "device_control_data.h"
#include "fast_conble_func.h"

uint8_t *devList_p = NULL;    // 设备列表指针
cJSON *devList_Json = NULL;   // 设备列表JSON对象
uint8_t *sceneList_p = NULL;  // 场景列表指针
cJSON *sceneList_Json = NULL; // 场景列表JSON对象
uint8_t *groupList_p = NULL;  // 群组列表指针
cJSON *groupList_Json = NULL; // 群组列表JSON对象
uint8_t *roomList_p = NULL;   // 房间列表指针
cJSON *roomList_Json = NULL;  // 房间列表JSON对象

DOUSTR devAttribute_replace[] = {{"CF_DeviceId", "sdid"}, {"CF_Name", "devname"}, {"CF_ProductId", "spid"}};
#define devAttribute_replace_SIZE sizeof(devAttribute_replace) / sizeof(devAttribute_replace[0])

DOUSTR sceneAttribute_replace[] = {{"CF_SceneId", "moduleid"}, {"CF_RegionId", "roomId"}, {"CF_GroupId", "groupId"}};
#define sceneAttribute_replace_SIZE sizeof(sceneAttribute_replace) / sizeof(sceneAttribute_replace[0])

// 属性名称替换，包含上面两个
DOUSTR attributeName_replace[] = {
    {"CF_DeviceId", "sdid"}, {"CF_Name", "devname"}, {"CF_ProductId", "spid"}, {"CF_SceneId", "moduleid"}, {"CF_RegionId", "roomId"}, {"CF_RegionName", "roomName"}, {"CF_GroupId", "groupId"}, {"CF_GroupName", "groupName"}, {"\"CF_SceneName\"", "\"name\""} /*name与前面的devname有冲突，要全词匹配*/
};
#define attributeName_replace_SIZE sizeof(attributeName_replace) / sizeof(attributeName_replace[0])

// 需要设备上报数据的列表
uint8_t *attributeName_report[] = {"CF_OnOff", "CF_Bright", "CF_ColorTemp"};
#define attributeName_report_SIZE sizeof(attributeName_report) / sizeof(attributeName_report[0])
uint16_t attributeName_report_SIZEfunc() // 其他文件使用需要函数形式，无法宏定义
{
    return sizeof(attributeName_report) / sizeof(attributeName_report[0]);
}

/**
 * @description: 字符串替换，返回的为新开辟的内存，需要手动释放
 * @param {char} *input 原串
 * @param {char} *pattern 旧子串
 * @param {char} *replacement 替换的新子串
 * @return {*} 返回新串
 */
char *replace_string(const char *input, const char *pattern, const char *replacement)
{
    char *result = NULL;
    size_t result_len = 0;
    const char *ptr = input;
    size_t pattern_len = strlen(pattern);
    size_t replacement_len = strlen(replacement);

    while (*ptr)
    {
        const char *match = strstr(ptr, pattern);
        if (match == NULL)
        {
            size_t remaining_len = strlen(ptr);
            result = realloc(result, result_len + remaining_len + 1);
            if (result == NULL)
            {
                fprintf(stderr, "Memory allocation failed\n");
                return NULL;
            }
            strcpy(result + result_len, ptr);
            result_len += remaining_len;
            break;
        }

        size_t segment_len = match - ptr;
        result = realloc(result, result_len + segment_len + replacement_len + 1);
        if (result == NULL)
        {
            fprintf(stderr, "Memory allocation failed\n");
            return NULL;
        }

        strncpy(result + result_len, ptr, segment_len);
        strcpy(result + result_len + segment_len, replacement);
        result_len += segment_len + replacement_len;

        ptr = match + pattern_len;
    }

    result = realloc(result, result_len + 1);
    if (result == NULL)
    {
        fprintf(stderr, "Memory allocation failed\n");
        return NULL;
    }
    result[result_len] = '\0';

    return result;
}

/**
 * @description: 格式化字符串，内部使用malloc自动分配内存，不用担心使用数组不够大时出错
 * @param {char*} format 格式化
 * @return {*} 返回指针，使用后需要free释放内存
 */
char *format_string(const char *format, ...)
{
    va_list args1, args2;
    va_start(args1, format);

    // 计算格式化后字符串的长度
    int size = vsnprintf(NULL, 0, format, args1);
    if (size < 0)
    {
        va_end(args1);
        return NULL;
    }

    // 分配足够的内存来存储格式化后的字符串
    char *str = (char *)malloc(size + 1);
    if (!str)
    {
        va_end(args1);
        return NULL;
    }

    // 使用另一个参数列表来格式化字符串
    va_start(args2, format);
    vsnprintf(str, size + 1, format, args2);
    va_end(args2);

    va_end(args1);

    return str;
}

/**
 * @description: 字符串复制时自动分配内存
 * @param {char*} src 源字符串
 * @return {*} 返回分配的地址，使用后需要free释放
 */
char *strdup_custom(const char *src)
{
    size_t len = strlen(src);
    char *dest = (char *)malloc(len + 1); // 分配足够的内存来存储字符串和结尾的空字符
    if (dest)
    {
        strcpy(dest, src); // 复制字符串
    }
    return dest;
}

// 确定输出的为数值类型
/**
 * @description: 确定输出的为数值类型
 * @param {cJSON} *obj 对象（替换时需要对象）
 * @param {cJSON} *child 键值对
 * @param {int} value 数值
 * @return {*} 返回0成功，返回-1键值对类型不是数值和字符型
 */
int cJSON_setReplaceNumberValue(cJSON *obj, cJSON *child, int value)
{
    if (child->type == cJSON_Number)
    {
        cJSON_SetNumberValue(child, value);
        return 0;
    }
    else if (child->type == cJSON_String) // 需要做替换
    {
        cJSON_ReplaceItemInObject(obj, child->string, cJSON_CreateNumber(value));
        return 0;
    }
    return -1;
}

/**
 * @description: 获取设备列表
 * @param {uint8_t} *text设备列表文本
 * @return {*}返回cjson对象
 */
void devList_get(uint8_t *text)
{
    int textLen = strlen(text);
    if (devList_p != NULL)
    {
        free(devList_p); // 释放原空间
    }

    devList_p = (uint8_t *)malloc(textLen + 1);
    if (devList_p == NULL)
    {
        return; // 分配出错
    }
    memset(devList_p, 0, textLen + 1);
    strncpy(devList_p, text, textLen);

    if (devList_Json != NULL)
    {
        free(devList_Json); // 释放原空间
    }
    devList_Json = cJSON_Parse(devList_p); // 解析JSON
    log_info("devList_get");
}

// 获取列表
/**
 * @description: 获取列表
 * @param {uint8_t} *text 输入文本
 * @param {uint8_t} *listText_p 新存储的文本
 * @param {cJSON} *root 解析后的json对象
 * @return {*}返回1，分配存储出错，返回0正确执行
 */
int listJson_get(uint8_t *text, uint8_t **listText_p, cJSON **root)
{
    int textLen = strlen(text);
    if (*root != NULL)
    {
        free(*listText_p); // 释放原空间
    }

    *listText_p = (uint8_t *)calloc(textLen + 1, 1);
    if (*listText_p == NULL)
    {
        return 1; // 分配出错
    }
    strncpy(*listText_p, text, textLen);

    if (*root != NULL)
    {
        free(*root); // 释放原空间
    }
    *root = cJSON_Parse(*listText_p); // 解析JSON
    log_info("List_get");
    return 0;
}

/**
 * @description:mqtt客户端的属性与服务端属性名称对应
 * @param {uint8_t} *cli_name输入的客户端名称
 * @param {uint8_t} *ser_name对应的输出客户端名称
 * @return {*} 0查找到返回查找到的字符串，1没有查找到返回原字符串
 */
int sceneAttribute_rename(uint8_t *cli_name, uint8_t *ser_name)
{
    uint16_t i;

    if (cli_name == NULL) // 检查传入参数
    {
        log_error("null string");
        return 2;
    }

    for (i = 0; i < sceneAttribute_replace_SIZE; i++)
    {
        if (!strcmp(cli_name, sceneAttribute_replace[i].str1)) // 匹配成功
        {
            // ser_name = devAttribute_replace[i].str2;  //这里注意，可能要采用复制的方法
            strcpy(ser_name, sceneAttribute_replace[i].str2);
            return 0;
        }
    }
    strcpy(ser_name, cli_name); // 没有找到列表字符串
    return 1;
}

/**
 * @description:mqtt客户端的属性与服务端属性名称对应
 * @param {uint8_t} *cli_name输入的客户端名称
 * @param {uint8_t} *ser_name对应的输出客户端名称
 * @return {*} 0查找到返回查找到的字符串，1没有查找到返回原字符串
 */
int devAttribute_rename(uint8_t *cli_name, uint8_t *ser_name)
{
    uint16_t i;
    for (i = 0; i < devAttribute_replace_SIZE; i++)
    {
        if (!strcmp(cli_name, devAttribute_replace[i].str1)) // 匹配成功
        {
            // ser_name = devAttribute_replace[i].str2;  //这里注意，可能要采用复制的方法
            strcpy(ser_name, devAttribute_replace[i].str2);
            return 0;
        }
    }
    strcpy(ser_name, cli_name); // 没有找到列表字符串
    return 1;
}

/**
 * @description:mqtt客户端的属性与服务端属性名称对应
 * @param {uint8_t} *cli_name输入的客户端名称
 * @param {uint8_t} **ser_name返回指针即可，不用复制字符串
 * @return {*} 0查找到返回查找到的字符串，1没有查找到返回原字符串
 */
int attributeName_rename(uint8_t *cli_name, uint8_t **ser_name)
{
    uint16_t i;
    for (i = 0; i < attributeName_replace_SIZE; i++)
    {
        if (!strcmp(cli_name, attributeName_replace[i].str1)) // 匹配成功
        {
            // ser_name = devAttribute_replace[i].str2;  //这里注意，可能要采用复制的方法
            // strcpy(ser_name, attributeName_replace[i].str2);
            *ser_name = attributeName_replace[i].str2;
            return 0;
        }
    }
    *ser_name = cli_name; // 原值，不重命名
    return 1;
}

char *attributeToSerName(char *msg)
{
    char *textOld = strdup(msg);
    char *textNew = NULL;
    for (int i = 0; i < attributeName_replace_SIZE; i++)
    {
        textNew = replace_string(textOld, attributeName_replace[i].str1, attributeName_replace[i].str2);
        // free(textOld);
        textOld = textNew;
    }
    return textNew;
}
char *attributeToMqttName(char *msg)
{
    char *textOld = strdup(msg);
    char *textNew = NULL;
    for (int i = 0; i < attributeName_replace_SIZE; i++)
    {
        textNew = replace_string(textOld, attributeName_replace[i].str2, attributeName_replace[i].str1);
        free(textOld);
        textOld = textNew;
    }
    return textNew;
}

/**
 * @description: json键值修改为服务器字符串形式, 使用在名称转换之后
 * @param {cJSON} *json 输入json键值对
 * @return {*}
 */
int jsonValueToSerStr(cJSON *json)
{ // 处理返回的data数据段
    if (json == NULL)
    {
        return -1;
    }

    cJSON *id = cJSON_GetObjectItemCaseSensitive(json, "id");
    if (id != NULL)
    {
        if (strlen(id->valuestring) == 12) // 12位的长度为设备id
        {
            uint8_t _id[33] = {0}; // 有效长度32
            memset(_id, '0', 20);
            memcpy(_id + 20, id->valuestring, 12); // 在传入id前加20个‘0’
            cJSON_SetValuestring(id, _id);
            // printf("%s\n", cJSON_Print(json));
        }
    }
    cJSON *filter = cJSON_GetObjectItemCaseSensitive(json, "filter"); // 是数组
    if (filter != NULL)
    {
        cJSON *element = NULL;
        cJSON_ArrayForEach(element, filter) // 是数组
        {
            // 不用while next遍历，只对特定项处理即可，若没有特定项则不处理
            cJSON *spid = cJSON_GetObjectItemCaseSensitive(element, "spid"); // CF_ProductId, 在换名后使用
            if (spid != NULL)
            {
                uint8_t ch[33] = {0}; // 小端05aa->0xaa05
                memset(ch, '0', 32);
                memcpy(ch + 24, spid->valuestring, 4);
                cJSON_SetValuestring(spid, ch);
            }
        }
    }
    cJSON *config = cJSON_GetObjectItemCaseSensitive(json, "config"); // 是数组
    if (config != NULL)
    {
        cJSON *element = NULL;
        cJSON_ArrayForEach(element, config) // 是数组
        {
            // 不用while next遍历，只对特定项处理即可，若没有特定项则不处理
            cJSON *spid = cJSON_GetObjectItemCaseSensitive(element, "spid"); // CF_ProductId, 在换名后使用
            if (spid != NULL)
            {
                uint8_t ch[33] = {0}; // 小端05aa->0xaa05
                memset(ch, '0', 32);
                memcpy(ch + 24, spid->valuestring, 4);
                cJSON_SetValuestring(spid, ch);
            }
        }
    }
}
void jsonValueToSerIteration(cJSON *item)
{
    if (item == NULL)
    {
        return;
    }

    switch (item->type)
    {
    case cJSON_Object:
    {
        // printf("Object:\n");
        cJSON *child = item->child;
        while (child != NULL)
        {
            // printf("Key: %s\n", child->string);
            jsonValueToSerIteration(child);
            child = child->next;
        }
    }
    break;
    case cJSON_Array:
    {
        // printf("Array:\n");
        cJSON *child = item->child;
        int index = 0;
        while (child != NULL)
        {
            // printf("Index: %d\n", index);
            jsonValueToSerIteration(child);
            child = child->next;
            index++;
        }
    }
    break;
    case cJSON_String:
        jsonValueToSerStr(item);
        // printf("String: %s\n", item->valuestring);
        break;
    case cJSON_Number:
        // printf("Number: %f\n", item->valuedouble);
        break;
    case cJSON_True:
        // printf("True\n");
        break;
    case cJSON_False:
        // printf("False\n");
        break;
    case cJSON_NULL:
        // printf("Null\n");
        break;
    default:
        // printf("Unknown type\n");
        break;
    }
}

/**
 * @description: json键值修改为mqtt字符串形式
 * @param {cJSON} *json 输入json键值对
 * @return {*}
 */
int jsonValueToMqttStr(cJSON *json)
{
#if 0 // 这部分代码不知原因的出现内存问题
//找到原因，对传入的指针，不轻易修改其指向，外部可能还要用到
    if (json == NULL)
    {
        return -1;
    }

    if (!strcmp(json->string, "id"))
    {
        if (strlen(json->valuestring) == 32) // 32位的长度为设备id
        {
            uint8_t _id[13] = {0}; // 有效长度32
            memcpy(_id, json->valuestring+20, 12);
            cJSON_SetValuestring(json, _id);
            // printf("%s\n", cJSON_Print(json));
        }
    }
#endif
    // 对回复的data键值处理
    // printf("json:\n%s\n", cJSON_Print(json));
    cJSON *id = cJSON_GetObjectItemCaseSensitive(json, "id");
    if (id != NULL)
    {
        if (strlen(id->valuestring) == 32) // 32位的长度为设备id
        {
            uint8_t _id[13] = {0}; // 有效长度32
            memcpy(_id, id->valuestring + 20, 12);
            cJSON_SetValuestring(id, _id);
            // printf("%s\n", cJSON_Print(json));
        }
    }
    // printf("json:\n%s\n", cJSON_Print(json));
}

// 修改了内部函数，此函数舍弃不用，直接用内部函数
void jsonValueToMqttIteration(cJSON *item)
{
    if (item == NULL)
    {
        return;
    }

    switch (item->type)
    {
    case cJSON_Object:
    {
        // printf("Object:\n");
        cJSON *child = item->child;
        while (child != NULL)
        {
            // printf("Key: %s\n", child->string);
            jsonValueToMqttIteration(child);
            child = child->next;
        }
    }
    break;
    case cJSON_Array:
    {
        // printf("Array:\n");
        cJSON *child = item->child;
        int index = 0;
        while (child != NULL)
        {
            // printf("Index: %d\n", index);
            jsonValueToMqttIteration(child);
            child = child->next;
            index++;
        }
    }
    break;
    case cJSON_String:
        jsonValueToMqttStr(item);
        // printf("String: %s\n", item->valuestring);
        break;
    case cJSON_Number:
        // printf("Number: %f\n", item->valuedouble);
        break;
    case cJSON_True:
        // printf("True\n");
        break;
    case cJSON_False:
        // printf("False\n");
        break;
    case cJSON_NULL:
        // printf("Null\n");
        break;
    default:
        // printf("Unknown type\n");
        break;
    }
}
/**
 * @description: 根据设备ID索引，找到设备属性
 * @param {uint8_t} *devID 设备ID,32位
 * @param {uint8_t} *attr 设备属性
 * @param {uint8_t} *value 返回值，复制到该指针，有大小限制2048
 * @return {*} 0查找到，1没有找到设备，2没有找到属性，3返回字符串超过2048个，4解析json没有对象
 */
int devList_getAttribute(uint8_t *devID, uint8_t *attr, uint8_t *value)
{
    cJSON *root;
    root = devList_Json;
    int arraySize = cJSON_GetArraySize(root);
    int i;
    for (i = 0; i < arraySize; i++)
    {
        cJSON *item = cJSON_GetArrayItem(root, i);
        if (!cJSON_IsObject(item))
        {
            printf("Error: Item at index %d is not a number.\n", i);
            cJSON_Delete(root);
            // free(jsonString);
            return 4; // 没有设备
        }
        cJSON *_devID = cJSON_GetObjectItemCaseSensitive(item, "sdid");
        if (_devID != NULL)
        {
            if (!strcmp(_devID->valuestring, devID))
            {
                // log_info("deviceID");
                cJSON *attrJSON = cJSON_GetObjectItemCaseSensitive(item, attr);
                if (attrJSON != NULL)
                {
                    // printf("%s\n", attrJSON->valuestring);
                    if (strlen(attrJSON->valuestring) >= 2048)
                    {
                        return 3; // 返回的属性字符串过多
                    }
                    else
                    {
                        strcpy(value, attrJSON->valuestring);
                    }
                    return 0; // 查找到
                }
                else
                {
                    return 2; // 没找到该属性
                }
            }
        }
        else
        {
        }
    }
    return 1; // 没找到该设备
}

/**
 * @description: 根据设备ID索引，找到设备属性
 * @param {uint8_t} *devID 设备ID,32位
 * @param {uint8_t} *attr 设备属性
 * @param {uint8_t} *value 返回值，复制到该指针，有大小限制2048
 * @return {*} 0查找到，1没有找到设备，2没有找到属性，3返回字符串超过2048个，4解析json没有对象, 5json数据为空, 6没有找到id项
 */
int sceneList_getAttribute(uint8_t *devID, uint8_t *attr, uint8_t *value)
{
    cJSON *root;
    root = sceneList_Json;
    if (root == NULL)
        return 5;
    int arraySize = cJSON_GetArraySize(root);
    int i;

    for (i = 0; i < arraySize; i++)
    {
        cJSON *item = cJSON_GetArrayItem(root, i);
        if (!cJSON_IsObject(item))
        {
            printf("Error: Item at index %d is not a number.\n", i);
            cJSON_Delete(root);
            // free(jsonString);
            return 4; // 没有设备
        }
        cJSON *_devID = cJSON_GetObjectItemCaseSensitive(item, "moduleid");

        if (_devID != NULL)
        {
            if (!strcmp(_devID->valuestring, devID))
            {
                // log_info("deviceID");
                cJSON *attrJSON = cJSON_GetObjectItemCaseSensitive(item, attr);
                if (attrJSON != NULL)
                {
                    if (cJSON_IsString(attrJSON)) // 在这里区分是有问题的，需要返回json对象才正确
                    {
                        // printf("%s\n", attrJSON->valuestring);
                        if (strlen(attrJSON->valuestring) >= 2048)
                        {
                            return 3; // 返回的属性字符串过多
                        }
                        else
                        {

                            strcpy(value, attrJSON->valuestring);
                        }
                    }
                    if (cJSON_IsNumber(attrJSON))
                    {
                    }
                    return 0; // 查找到
                }
                else
                {
                    return 2; // 没找到该属性
                }
            }
        }
        else
        {
            log_info("no id\n");
            return 6; // 没有找到id项
        }
    }
    return 1; // 没找到该设备
}

int sceneList_getAttributeJson(uint8_t *devID, cJSON **attr)
{
    cJSON *root;
    root = sceneList_Json;
    cJSON *_attr = *attr;  // 传入为单重指针
    uint8_t _id[20] = {0}; // id,
    if (root == NULL)
        return ERROR_INVALID_PARAM;
    int arraySize = cJSON_GetArraySize(root);
    int i;

    for (i = 0; i < arraySize; i++)
    {
        cJSON *item = cJSON_GetArrayItem(root, i);
        if (!cJSON_IsObject(item))
        {
            printf("Error: Item at index %d is not a number.\n", i);
            cJSON_Delete(root);
            // free(jsonString);
            return ERROR_JSON_NULL; // 没有设备
        }
        cJSON *_devID = cJSON_GetObjectItemCaseSensitive(item, "moduleid"); // 查找目标

        if (_devID != NULL)
        {
            if (cJSON_IsNumber(_devID))
            {
                snprintf(_id, sizeof(_id), "%d", _devID->valueint);
            }
            if (cJSON_IsString(_devID))
            {
                // printf("string\n");
                strcpy(_id, _devID->valuestring);
            }
            if (!strcmp(_id, devID))
            {
                // log_info("deviceID");
                // log_info("%s", _attr->string);
                // log_info("fa:%s", cJSON_Print(_attr));
                cJSON *attrJSON = cJSON_GetObjectItemCaseSensitive(item, _attr->string);
                if (attrJSON != NULL)
                {
                    // log_info("fa:%s", cJSON_Print(_attr));
                    cJSON_Delete(_attr);
                    _attr = cJSON_Duplicate(attrJSON, 1); // 这里获取到的是具体的值
                    return ERROR_NONE;                    // 查找到
                }
                else
                {
                    return ERROR_NOT_ATTR; // 没找到该属性
                }
            }
        }
        else
        {
            // log_info("no id\n");
        }
    }
    return ERROR_NOT_ID; // 没找到该设备
}

int groupList_getAttributeJson(uint8_t *devID, cJSON **attr)
{
    cJSON *root;
    root = groupList_Json;
    cJSON *_attr = *attr;  // 传入为单重指针
    uint8_t _id[20] = {0}; // id,
    if (root == NULL)
        return ERROR_INVALID_PARAM;
    int arraySize = cJSON_GetArraySize(root);
    int i;

    for (i = 0; i < arraySize; i++)
    {
        cJSON *item = cJSON_GetArrayItem(root, i);
        if (!cJSON_IsObject(item))
        {
            printf("Error: Item at index %d is not a number.\n", i);
            cJSON_Delete(root);
            // free(jsonString);
            return ERROR_JSON_NULL; // 没有设备
        }
        cJSON *_devID = cJSON_GetObjectItemCaseSensitive(item, "groupId"); // 查找目标

        if (_devID != NULL)
        {
            if (cJSON_IsNumber(_devID))
            {
                snprintf(_id, sizeof(_id), "%d", _devID->valueint);
            }
            if (cJSON_IsString(_devID))
            {
                // printf("string\n");
                strcpy(_id, _devID->valuestring);
            }
            log_info("_id:%s", _id);
            if (!strcmp(_id, devID))
            {
                // log_info("deviceID");
                // log_info("%s", _attr->string);
                // log_info("fa:%s", cJSON_Print(_attr));
                cJSON *attrJSON = cJSON_GetObjectItemCaseSensitive(item, _attr->string);
                // log_info("fa:%s", cJSON_Print(item));
                if (attrJSON != NULL)
                {
                    // log_info("fa:%s", cJSON_Print(_attr));
                    cJSON_Delete(_attr);
                    _attr = cJSON_Duplicate(attrJSON, 1); // 这里获取到的是具体的值
                    return ERROR_NONE;                    // 查找到
                }
                else
                {
                    return ERROR_NOT_ATTR; // 没找到该属性
                }
            }
        }
        else
        {
            // log_info("no id\n");
        }
    }
    return ERROR_NOT_ID; // 没找到该设备
}
/**
 * @description: json数据查询解析
 * @param {uint8_t} *devID
 * @param {cJSON} *json
 * @return {*}
 */
void checkJson(uint8_t *devID, cJSON *json)
{
    if (json == NULL)
    {
        return;
    }

    switch (json->type)
    {
    case cJSON_Object:
    {
        cJSON *child = json->child;
        while (child != NULL)
        {
            checkJson(devID, child);
            printf("Key: %s\n", child->string);
            // if(!strcmp(child->string, "CF_Name"))
            // {
            //     cJSON_SetValuestring(child, "test");
            //     printJson(child);
            // }
            child->string;
            uint8_t serNameReplace[2048] = {0};
            uint8_t serNameValue[2048] = {0};
            sceneAttribute_rename(child->string, serNameReplace);
            uint8_t ret = devList_getAttribute(devID, serNameReplace, serNameValue);
            cJSON_SetValuestring(child, serNameValue);
            printf("Key1: %s\n", serNameReplace);
            printf("Key2: %s\n", serNameValue);
            printf("Key3: %d\n", ret);
            child = child->next;
        }
        break;
    }
    case cJSON_Array:
    {
        cJSON *child = json->child;
        int i = 0;
        while (child != NULL)
        {
            printf("[%d]:\n", i++);
            checkJson(devID, child);
            child = child->next;
        }
        break;
    }
    case cJSON_String:
        printf("String: %s\n", json->valuestring);
        break;
    case cJSON_Number:
        printf("Number: %g\n", json->valuedouble);
        break;
    case cJSON_True:
        printf("True\n");
        break;
    case cJSON_False:
        printf("False\n");
        break;
    case cJSON_NULL:
        printf("Null\n");
        break;
    default:
        printf("Unknown\n");
        break;
    }
}

int checkDevJson(uint8_t *devID, cJSON *json)
{
    int ret = 0;
    if (json == NULL || devID == NULL) // 传入参数检查
    {
        return ERROR_INVALID_PARAM;
    }

    cJSON *element = NULL;
    cJSON_ArrayForEach(element, json) // element是含一个键值对的对象
    {
        cJSON *child = element->child; // 键值对
        while (child != NULL)          // 对象内多个键值对问题
        {
            // uint8_t *serNameReplace = NULL;
            // attributeName_rename(child->string, &serNameReplace);  //不用此方法

            cJSON *_element = cJSON_CreateObject();
            // cJSON_AddStringToObject(_element, serNameReplace, "");
            cJSON_AddStringToObject(_element, child->string, "");
            cJSON *index = cJSON_CreateObject();
            cJSON_AddStringToObject(index, "sdid", devID);
            list_getOneAttrJson(devList_Json, index, &_element);
            cJSON_SetValuestring(child, _element->child->valuestring);
            cJSON_free(_element);
            cJSON_free(index);
            child = child->next;
        }
    }
    return ERROR_NONE;
}

/**
 * @description: json数据查询解析
 * @param {uint8_t} *devID
 * @param {cJSON} *json
 * @return {*}
 */
int check_sceneJson(uint8_t *devID, cJSON *json)
{
    int ret = 0;
    if (json == NULL || devID == NULL) // 传入参数检查
    {
        return ERROR_INVALID_PARAM;
    }

    switch (json->type)
    {
    case cJSON_Object:
    {
        cJSON *child = json->child; // 这里的child是{}对象里的一个键值
        while (child != NULL)
        {
            check_sceneJson(devID, child);
            // 传入json对象，查找对应值填入
            ret = scencJson_newValue(devID, &child);
            if (ret == ERROR_NOT_ID) // 没有查找的ID，直接返回
            {
                return ERROR_NOT_ID;
            }
            child = child->next;
        }
        break;
    }
    case cJSON_Array:
    {
        cJSON *child = json->child;
        int i = 0;
        while (child != NULL)
        {
            // printf("[%d]:\n", i++);
            check_sceneJson(devID, child);
            if (ret == ERROR_NOT_ID) // 没有查找的ID，直接返回
            {
                return ERROR_NOT_ID;
            }
            child = child->next;
        }
        break;
    }
    case cJSON_String:
        // printf("String: %s\n", json->valuestring);
        break;
    case cJSON_Number:
        printf("Number: %g\n", json->valuedouble);
        break;
    case cJSON_True:
        printf("True\n");
        break;
    case cJSON_False:
        printf("False\n");
        break;
    case cJSON_NULL:
        printf("Null\n");
        break;
    default:
        printf("Unknown\n");
        break;
    }
    return ret;
}

/**
 * @description: json数据查询解析
 * @param {uint8_t} *devID
 * @param {cJSON} *json
 * @return {*}
 */
int checkSceneJson(uint8_t *devID, cJSON *json)
{
    int ret = 0;
    if (json == NULL || devID == NULL) // 传入参数检查
    {
        return ERROR_INVALID_PARAM;
    }

    cJSON *element = NULL;
    cJSON_ArrayForEach(element, json) // element是含一个键值对的对象
    {
        cJSON *child = element->child; // 键值对
        while (child != NULL)          // 对象内多个键值对问题
        {
            // uint8_t *serNameReplace = NULL;
            // attributeName_rename(child->string, &serNameReplace);  //不用此方法

            cJSON *_element = cJSON_CreateObject();
            // cJSON_AddStringToObject(_element, serNameReplace, "");
            cJSON_AddStringToObject(_element, child->string, "");
            cJSON *index = cJSON_CreateObject();
            cJSON_AddStringToObject(index, "moduleid", devID);
            ret = list_getOneAttrJson(sceneList_Json, index, &_element);
            // log_info("name:%s", child->string);
            // log_info("name:%s", serNameReplace);
            // log_info("attr:%d", ret);
            // log_info("json:%s", cJSON_Print(_element));
            cJSON_SetValuestring(child, _element->child->valuestring);
            cJSON_free(_element);
            cJSON_free(index);
            child = child->next;
        }
    }
    // log_info("%s", cJSON_Print(json));
    return ERROR_NONE;
}

/**
 * @description: 场景json查找数据
 * @param {uint8_t} *id 场景id
 * @param {cJSON} * cjson双重指针
 * @return {*}
 */
int scencJson_newValue(uint8_t *id, cJSON **objectJson)
{
    cJSON *_objectJson = *objectJson;
    cJSON *newJson = cJSON_CreateObject(); // 对象，内含键值对
    cJSON *newJson1 = NULL;                // 键值对

    uint8_t serNameReplace[2048] = {0};
    int ret = 0;

    if (id == NULL || _objectJson == NULL) // 检查传入参数
    {
        return ERROR_INVALID_PARAM;
    }

    ret = sceneAttribute_rename(_objectJson->string, serNameReplace); // 转为服务器上的键名
    if (ret >= 2)                                                     // 出错
    {
        return ERROR_OUT_OF_MEMORY;
    }

    cJSON_AddNullToObject(newJson, serNameReplace);  // 对象
    newJson1 = newJson->child;                       // 键值对
    ret = sceneList_getAttributeJson(id, &newJson1); // 获取属性的json
    switch (ret)                                     // 对获取属性方法返回值做不同处理
    {
    case ERROR_INVALID_PARAM:
        return ERROR_INVALID_PARAM;
        break;
    case ERROR_OUT_OF_MEMORY:
        return ERROR_OUT_OF_MEMORY;
        break;
    case ERROR_NOT_ID:
        return ERROR_NOT_ID;
        break;
    default: // ERROR_NONE,ERROR_NOT_ATTR
        break;
    }
    if (cJSON_IsNumber(newJson1)) // 数字需要转为字符串
    {
        uint8_t ch[20] = {0}; // 64位需要16个0-9字符表示
        snprintf(ch, sizeof(ch), "%d", newJson1->valueint);
        cJSON_SetValuestring(_objectJson, ch);
    }
    else if (cJSON_IsString(newJson1))
    {
        cJSON_SetValuestring(_objectJson, newJson1->valuestring);
    }
    else
    {
        cJSON_SetValuestring(_objectJson, "");
    }

    return 0;
}

/**
 * @description: json数据查询解析
 * @param {uint8_t} *devID
 * @param {cJSON} *json
 * @return {*} 1传参出错
 */
int check_groupJson(uint8_t *devID, cJSON *json)
{
    int ret = 0;
    if (json == NULL || devID == NULL) // 传入参数检查
    {
        return ERROR_INVALID_PARAM;
    }

    switch (json->type)
    {
    case cJSON_Object:
    {
        cJSON *child = json->child; // 这里的child是{}对象里的一个键值
        while (child != NULL)
        {
            check_groupJson(devID, child);
            // 传入json对象，查找对应值填入
            // ret = groupJson_newValue(devID, &child);
            ret = listJson_newValue(groupList_Json, "groupId", devID, &child);
            printf("ret1:%d\n", ret);
            if (ret == ERROR_NOT_ID) // 没有查找的ID，直接返回
            {
                return ERROR_NOT_ID;
            }
            child = child->next;
        }
        break;
    }
    case cJSON_Array:
    {
        cJSON *child = json->child;
        int i = 0;
        while (child != NULL)
        {
            // printf("[%d]:\n", i++);
            ret = check_groupJson(devID, child);
            printf("ret2:%d\n", ret);
            if (ret == ERROR_NOT_ID) // 没有查找的ID，直接返回
            {
                return ERROR_NOT_ID;
            }
            child = child->next;
        }
        break;
    }
    case cJSON_String:
        // printf("String: %s\n", json->valuestring);
        break;
    case cJSON_Number:
        printf("Number: %g\n", json->valuedouble);
        break;
    case cJSON_True:
        printf("True\n");
        break;
    case cJSON_False:
        printf("False\n");
        break;
    case cJSON_NULL:
        printf("Null\n");
        break;
    default:
        printf("Unknown\n");
        break;
    }

    return ret;
}

int checkRoomJson(uint8_t *devID, cJSON *json)
{
    int ret = 0;
    if (json == NULL || devID == NULL) // 传入参数检查
    {
        return ERROR_INVALID_PARAM;
    }

    // log_info("json:%s", cJSON_Print(json));
    cJSON *element = NULL;
    cJSON_ArrayForEach(element, json) // element是含一个键值对的对象
    {
        cJSON *child = element->child; // 键值对
        while (child != NULL)          // 对象内多个键值对问题
        {
            // uint8_t *serNameReplace = NULL;
            // attributeName_rename(child->string, &serNameReplace); // 不用此方法

            cJSON *_element = cJSON_CreateObject();
            // cJSON_AddStringToObject(_element, serNameReplace, "");
            cJSON_AddStringToObject(_element, child->string, "");
            cJSON *index = cJSON_CreateObject();
            cJSON_AddStringToObject(index, "roomId", devID);
            ret = list_getOneAttrJson(groupList_Json, index, &_element);
            // log_info("name:%s", child->string);
            // log_info("name:%s", serNameReplace);
            // log_info("attr:%d", ret);
            // log_info("json:%s", cJSON_Print(_element));
            cJSON_SetValuestring(child, _element->child->valuestring);
            cJSON_free(_element);
            cJSON_free(index);
            child = child->next;
        }
    }
    // log_info("%s", cJSON_Print(json));
    return ERROR_NONE;
}

/**
 * @description: json数据查询解析, mqtt传入id为字符串，json内存储为数值
 * @param {uint8_t} *devID
 * @param {cJSON} *json 为对象数组
 * @return {*} 1传参出错
 */
int checkGroupJson(uint8_t *devID, cJSON *json)
{
    int ret = 0;
    if (json == NULL || devID == NULL) // 传入参数检查
    {
        return ERROR_INVALID_PARAM;
    }

    // log_info("json:%s", cJSON_Print(json));
    cJSON *element = NULL;
    cJSON_ArrayForEach(element, json) // element是含一个键值对的对象
    {
        cJSON *child = element->child; // 键值对
        while (child != NULL)          // 对象内多个键值对问题
        {
            // uint8_t *serNameReplace = NULL;
            // attributeName_rename(child->string, &serNameReplace); // 不用此方法

            cJSON *_element = cJSON_CreateObject();
            // cJSON_AddStringToObject(_element, serNameReplace, "");
            cJSON_AddStringToObject(_element, child->string, "");
            cJSON *index = cJSON_CreateObject();
            cJSON_AddStringToObject(index, "groupId", devID);
            ret = list_getOneAttrJson(groupList_Json, index, &_element);
            // log_info("name:%s", child->string);
            // log_info("name:%s", serNameReplace);
            // log_info("attr:%d", ret);
            // log_info("json:%s", cJSON_Print(_element));
            cJSON_SetValuestring(child, _element->child->valuestring);
            cJSON_free(_element);
            cJSON_free(index);
            child = child->next;
        }
    }
    // log_info("%s", cJSON_Print(json));
    return ERROR_NONE;
}

/**
 * @description: 群组json查找数据
 * @param {uint8_t} *id 群组id
 * @param {cJSON} * cjson双重指针
 * @return {*} 0正常，1传入参数出错，2键名出错
 */
int groupJson_newValue(uint8_t *id, cJSON **objectJson)
{
    cJSON *_objectJson = *objectJson;
    cJSON *newJson = cJSON_CreateObject(); // 对象，内含键值对
    cJSON *newJson1 = NULL;                // 键值对

    uint8_t serNameReplace[2048] = {0}; // 暂存服务器的键名
    uint8_t ret = 0;

    if (id == NULL || _objectJson == NULL) // 检查传入参数
    {
        return ERROR_INVALID_PARAM;
    }

    ret = sceneAttribute_rename(_objectJson->string, serNameReplace); // 转为服务器上的键名
    if (ret >= 2)                                                     // 出错
    {
        return ERROR_OUT_OF_MEMORY;
    }

    // group群组与scene场景使用同一个修改名称
    cJSON_AddNullToObject(newJson, serNameReplace); // 对象
    newJson1 = newJson->child;                      // 键值对
    // ret = groupList_getAttributeJson(id, &newJson1); // 获取属性的json
    ret = list_getAttributeJson(groupList_Json, "groupId", id, &newJson1);
    printf("ret3:%d\n", ret);
    switch (ret) // 对获取属性方法返回值做不同处理
    {
    case ERROR_INVALID_PARAM:
        return ERROR_INVALID_PARAM;
        break;
    case ERROR_OUT_OF_MEMORY:
        return ERROR_OUT_OF_MEMORY;
        break;
    case ERROR_NOT_ID:
        return ERROR_NOT_ID;
        break;
    default: // ERROR_NONE,ERROR_NOT_ATTR
        break;
    }

    if (cJSON_IsNumber(newJson1)) // 数字需要转为字符串
    {
        uint8_t ch[20] = {0}; // 64位需要16个0-9字符表示
        snprintf(ch, sizeof(ch), "%d", newJson1->valueint);
        cJSON_SetValuestring(_objectJson, ch);
    }
    else if (cJSON_IsString(newJson1))
    {
        cJSON_SetValuestring(_objectJson, newJson1->valuestring);
    }
    else
    {
        cJSON_SetValuestring(_objectJson, "");
    }

    return 0;
}

int attribute_rename(uint8_t *cli_name, uint8_t *ser_name)
{
    uint16_t i;

    if (cli_name == NULL) // 检查传入参数
    {
        log_error("null string");
        return 2;
    }

    for (i = 0; i < sceneAttribute_replace_SIZE; i++)
    {
        if (!strcmp(cli_name, sceneAttribute_replace[i].str1)) // 匹配成功
        {
            // ser_name = devAttribute_replace[i].str2;  //这里注意，可能要采用复制的方法
            strcpy(ser_name, sceneAttribute_replace[i].str2);
            return 0;
        }
    }
    for (i = 0; i < devAttribute_replace_SIZE; i++)
    {
        if (!strcmp(cli_name, devAttribute_replace[i].str1)) // 匹配成功
        {
            // ser_name = devAttribute_replace[i].str2;  //这里注意，可能要采用复制的方法
            strcpy(ser_name, devAttribute_replace[i].str2);
            return 0;
        }
    }
    strcpy(ser_name, cli_name); // 没有找到列表字符串
    return 1;
}

// 合并group, scene, dev三个列表
/**
 * @description: 查找json列表里的属性
 * @param {cJSON} *list_Json 查找的列表
 * @param {uint8_t} *index 索引的键名
 * @param {uint8_t} *devID 匹配的索引键名对应的键值
 * @param {cJSON} * 返回的属性，为键值对指针，区别于对象
 * @return {*}
 */
int list_getAttributeJson(cJSON *list_Json, uint8_t *index, uint8_t *devID, cJSON **attr)
{
    cJSON *root;
    root = list_Json;
    cJSON *_attr = *attr; // 传入为单重指针
    // uint8_t _id[20] = {0}; // id,  内存可能过小
    uint8_t *_id = NULL;
    if (root == NULL)
        return ERROR_INVALID_PARAM;
    int arraySize = cJSON_GetArraySize(root);
    int i;
    log_info("devID:%s", devID);
    for (i = 0; i < arraySize; i++)
    {
        cJSON *item = cJSON_GetArrayItem(root, i);
        if (!cJSON_IsObject(item))
        {
            printf("Error: Item at index %d is not a number.\n", i);
            cJSON_Delete(root);
            // free(jsonString);
            return ERROR_JSON_NULL; // 没有设备
        }
        // cJSON *_devID = cJSON_GetObjectItemCaseSensitive(item, "moduleid"); // 查找目标
        cJSON *_devID = cJSON_GetObjectItemCaseSensitive(item, index); // 查找目标

        if (_devID != NULL)
        {
            if (cJSON_IsNumber(_devID))
            {
                // snprintf(_id, sizeof(_id), "%d", _devID->valueint);
                _id = format_string("%d", _devID->valueint); // 改用这个
            }
            if (cJSON_IsString(_devID))
            {
                // printf("string\n");
                // strcpy(_id, _devID->valuestring);
                _id = strdup_custom(_devID->valuestring); // 改用这个
            }
            log_info("_id:%s", _id);
            uint8_t result = 0;
            result = strcmp(_id, devID); // 结束_id的使用并释放
            free(_id);
            if (!result)
            {
                // log_info("deviceID");
                // log_info("%s", _attr->string);
                // log_info("fa:%s", cJSON_Print(_attr));
                cJSON *attrJSON = cJSON_GetObjectItemCaseSensitive(item, _attr->string);
                if (attrJSON != NULL)
                {
                    // log_info("fa:%s", cJSON_Print(_attr));
                    cJSON_Delete(_attr);
                    _attr = cJSON_Duplicate(attrJSON, 1); // 这里获取到的是具体的值
                    return ERROR_NONE;                    // 查找到
                }
                else
                {
                    return ERROR_NOT_ATTR; // 没找到该属性
                }
            }
        }
        else
        {
            // log_info("no id\n");
        }
    }
    return ERROR_NOT_ID; // 没找到该设备
}

int listJson_newValue(cJSON *list_Json, uint8_t *index, uint8_t *id, cJSON **objectJson)
{
    cJSON *_objectJson = *objectJson;
    cJSON *newJson = cJSON_CreateObject(); // 对象，内含键值对
    cJSON *newJson1 = NULL;                // 键值对

    uint8_t serNameReplace[2048] = {0}; // 暂存服务器的键名
    int ret = 0;

    if (id == NULL || _objectJson == NULL) // 检查传入参数
    {
        return ERROR_INVALID_PARAM;
    }

    ret = attribute_rename(_objectJson->string, serNameReplace); // 转为服务器上的键名
    if (ret >= 2)                                                // 出错
    {
        return ERROR_OUT_OF_MEMORY;
    }

    // group群组与scene场景使用同一个修改名称
    cJSON_AddNullToObject(newJson, serNameReplace); // 对象
    newJson1 = newJson->child;                      // 键值对
    // ret = groupList_getAttributeJson(id, &newJson1); // 获取属性的json
    ret = list_getAttributeJson(list_Json, index, id, &newJson1);
    switch (ret) // 对获取属性方法返回值做不同处理
    {
    case ERROR_INVALID_PARAM:
        return ERROR_INVALID_PARAM;
        break;
    case ERROR_OUT_OF_MEMORY:
        return ERROR_OUT_OF_MEMORY;
        break;
    case ERROR_NOT_ID:
        return ERROR_NOT_ID;
        break;
    default: // ERROR_NONE,ERROR_NOT_ATTR
        break;
    }

    if (cJSON_IsNumber(newJson1)) // 数字需要转为字符串
    {
        uint8_t ch[20] = {0}; // 64位需要16个0-9字符表示
        snprintf(ch, sizeof(ch), "%d", newJson1->valueint);
        cJSON_SetValuestring(_objectJson, ch);
    }
    else if (cJSON_IsString(newJson1))
    {
        cJSON_SetValuestring(_objectJson, newJson1->valuestring);
    }
    else
    {
        cJSON_SetValuestring(_objectJson, "");
    }

    return 0;
}

int check_listJson(cJSON *list_Json, uint8_t *index, uint8_t *devID, cJSON *json)
{
    int ret = 0;
    if (json == NULL || devID == NULL) // 传入参数检查
    {
        return ERROR_INVALID_PARAM;
    }

    switch (json->type)
    {
    case cJSON_Object:
    {
        cJSON *child = json->child; // 这里的child是{}对象里的一个键值
        while (child != NULL)
        {
            check_listJson(list_Json, index, devID, child);
            // 传入json对象，查找对应值填入
            // ret = groupJson_newValue(devID, &child);
            ret = listJson_newValue(list_Json, index, devID, &child);
            printf("ret1:%d\n", ret);
            if (ret == ERROR_NOT_ID) // 没有查找的ID，直接返回
            {
                return ERROR_NOT_ID;
            }
            child = child->next;
        }
        break;
    }
    case cJSON_Array:
    {
        cJSON *child = json->child;
        int i = 0;
        while (child != NULL)
        {
            // printf("[%d]:\n", i++);
            ret = check_listJson(list_Json, index, devID, child);
            printf("ret2:%d\n", ret);
            if (ret == ERROR_NOT_ID) // 没有查找的ID，直接返回
            {
                return ERROR_NOT_ID;
            }
            child = child->next;
        }
        break;
    }
    case cJSON_String:
        // printf("String: %s\n", json->valuestring);
        break;
    case cJSON_Number:
        printf("Number: %g\n", json->valuedouble);
        break;
    case cJSON_True:
        printf("True\n");
        break;
    case cJSON_False:
        printf("False\n");
        break;
    case cJSON_NULL:
        printf("Null\n");
        break;
    default:
        printf("Unknown\n");
        break;
    }

    return ret;
}

/**
 * @description: 根据一个属性来获取列表的另一个属性，以存储json类型为准需要转换类型
 * @param {cJSON} *list_Json 列表
 * @param {cJSON} *index 查找属性 含一个键对的对象
 * @param {cJSON} ** 查找结果属性 含一个键对的对象，键名，查找键值
 * @return {*}
 */
int list_getOneAttrJson(cJSON *list_Json, cJSON *index, cJSON **result)
{
    cJSON *root = list_Json;
    cJSON *item = NULL;
    cJSON *_result = *result;
    int i = 0;
    if (root == NULL || index == NULL)
    {
        return ERROR_JSON_NULL;
    }
    if (cJSON_IsArray(root))
    {
        cJSON *element;
        element = cJSON_GetArrayItem(root, 0);
        cJSON_ArrayForEach(element, root) // element为数组内的对象，内含多个键对
        {
            cJSON *_index = cJSON_GetObjectItemCaseSensitive(element, (index->child)->string); // 键值对
            if (_index != NULL)                                                                // 存储的json
            {
                if (cJSON_IsNumber(_index))
                {
#if 0
                    uint8_t value[20] = {0};
                    snprintf(value, sizeof(value), "%d", _index->valueint);
                    if (!strcmp(value, (index->child)->valuestring)) // 匹配
                    {
                        item = element;
                    }
#endif
                    uint8_t *value = NULL;
                    value = format_string("%d", _index->valueint);
                    uint8_t strRet = 0;
                    strRet = strcmp(value, (index->child)->valuestring);
                    // printf("t:%d\n", _index->valueint);
                    // printf("te:%s\t%s\n", (index->child)->valuestring, value);
                    free(value);
                    if (!strRet)
                    {
                        item = element;
                    }
                }
                else if (cJSON_IsString(_index))
                {
                    if (!strcmp(_index->valuestring, (index->child)->valuestring)) // 匹配
                    {
                        item = element;
                    }
                }
                // i++;
                // printf("%d\n", i);
                // printf("%s\n", cJSON_Print(element));
            }
        }
        if (item == NULL)
        {
            return ERROR_NOT_ID;
        }
        cJSON *resultJson = cJSON_GetObjectItemCaseSensitive(item, (_result->child)->string); // 键值对
        if (resultJson == NULL)
        {
            return ERROR_NOT_ATTR;
        }
        if (cJSON_IsString(resultJson))
        {
            cJSON_SetValuestring(_result->child, resultJson->valuestring);
        }
        else if (cJSON_IsNumber(resultJson))
        {
            uint8_t *value = NULL;
            value = format_string("%d", resultJson->valueint);
            cJSON_SetValuestring(_result->child, value);
            free(value);
        }
    }
    else
    {
        return ERROR_NOT_ATTR;
    }
    return ERROR_NONE;
}

// 根据特定项返回对象的指针
/**
 * @description: 根据特定项返回对象的指针，索引内容不作改变
 * @param {cJSON} *list_Json 传入查找的列表的指针
 * @param {cJSON} *index 传入待查找的项目，为只含一个键值对的对象
 * @param {cJSON} * 返回对象指针
 * @return {*}
 */
// uint8_t searchJson(cJSON *root, cJSON *index, cJSON **result)
int list_getItemJson(cJSON *list_Json, cJSON *index, cJSON **item)
{
    cJSON *root = list_Json;
    int i = 0;
    if (root == NULL || index == NULL)
    {
        return ERROR_JSON_NULL;
    }
    if (cJSON_IsArray(root))
    {
        cJSON *element;
        element = cJSON_GetArrayItem(root, 0);
        cJSON_ArrayForEach(element, root) // element为数组内的对象，内含多个键对
        {
            cJSON *_index = cJSON_GetObjectItemCaseSensitive(element, (index->child)->string); // 键值对
            if (_index != NULL)
            {
                if (cJSON_IsNumber(_index))
                {
#if 0
                    uint8_t value[20] = {0};
                    snprintf(value, sizeof(value), "%d", _index->valueint);
                    if (!strcmp(value, (index->child)->valuestring)) // 匹配
                    {
                        *item = element;
                        return ERROR_NONE;
                    }
#endif

                    uint8_t *value = NULL;
                    value = format_string("%d", _index->valueint);
                    uint8_t result = 0;
                    result = strcmp(value, (index->child)->valuestring);
                    free(value);
                    if (!result)
                    {
                        *item = element;
                        return ERROR_NONE;
                    }
                }
                else if (cJSON_IsString(_index))
                {
                    if (!strcmp(_index->valuestring, (index->child)->valuestring)) // 匹配
                    {
                        *item = element;
                        return ERROR_NONE;
                    }
                }
            }
            // i++;
            // printf("%d\n", i);
            // printf("%s\n", cJSON_Print(element));
        }
        *item = NULL;
    }
    else
    {
        return ERROR_NOT_ATTR;
    }
}

// 更新
/**
 * @description: 更新列表中json成员
 * @param {cJSON} *list_Json 搜索的列表
 * @param {cJSON} *index 索引的json, 一个键值对的对象
 * @param {cJSON} *newJson 返回的结果，一个键值对的对象
 * @return {*}
 */
int list_updateItemJson(cJSON *list_Json, cJSON *index, cJSON *newJson)
{
    cJSON *item = NULL;
    cJSON *_newJson = NULL;
    int ret = 0;
    ret = list_getItemJson(list_Json, index, &item);
    if (item == NULL)
    {
        return ERROR_NOT_ID;
    }
    _newJson = cJSON_GetObjectItemCaseSensitive(item, newJson->child->string); // 获取是否存在
    if (_newJson == NULL)
    {
        if (cJSON_IsString(newJson->child))
        {
            cJSON_AddStringToObject(item, newJson->child->string, newJson->child->valuestring);
        }
    }
    else
    {
        if (cJSON_IsString(newJson->child))
        {
            cJSON_SetValuestring(_newJson, newJson->child->valuestring);
        }
    }
    return ERROR_NONE;
}

// 更新列表状态数据
int list_update_stateData(uint8_t *data, uint16_t dataLen, uint16_t addr)
{
    cJSON *addrJson = NULL;
    cJSON *stateDataJson = NULL;
    uint8_t ch[10] = {0};
    addrJson = cJSON_CreateObject();
    snprintf(ch, sizeof(ch), "%d", addr);
    cJSON_AddStringToObject(addrJson, "shortaddr", ch);

    stateDataJson = cJSON_CreateObject();

    uint8_t *dataStr = base64_encode(data, dataLen);
    cJSON_AddStringToObject(stateDataJson, "stateData", dataStr);
    free(dataStr);
    // printf("%s\n", cJSON_Print(addrJson));
    // printf("%s\n", cJSON_Print(stateDataJson));
    list_updateItemJson(devList_Json, addrJson, stateDataJson);

    free(addrJson);
    free(stateDataJson);
}

/**
 * @description: 检查index里的多个属性与item是否匹配, 全是字符串处理
 * @param {cJSON} *index 含多个键值对的对象
 * @param {cJSON} *item 检测的是否含index键值对的对象
 * @return {*}返回0匹配成功
 */
int matchItemJson(cJSON *index, cJSON *item)
{
    int ret = 0;
    cJSON *child = NULL;
    cJSON *result = NULL;
    uint8_t *renameStr = NULL;

    child = index->child;
    while (child != NULL)
    {
        // attributeName_rename(child->string, &renameStr);  // 不用此方法
        // result = cJSON_GetObjectItemCaseSensitive(item, renameStr);
        result = cJSON_GetObjectItemCaseSensitive(item, child->string);
        if (result != NULL)
        {
            if (cJSON_IsString(result))
            {
                if (!strcmp(child->valuestring, result->valuestring))
                {
                    ;
                }
                else
                {
                    return -1; // 结束查找，不匹配
                }
            }
            else if (cJSON_IsNumber(result))
            {
                uint8_t *p = format_string("%d", result->valueint);
                int ret_str = strcmp(child->valuestring, p);
                free(p);
                if (!ret_str)
                {
                    ;
                }
                else
                {
                    return -1; // 结束查找，不匹配
                }
            }
        }
        else
        {
            return -1; // 结束查找，不匹配
        }
        child = child->next;
    }
    return ERROR_NONE;
}

/**
 * @description: 获取item的内容
 * @param {cJSON} *index 返回的结果，必须为字符型
 * @param {cJSON} *item 查找的Item
 * @return {*}
 */
int updateItemJson(cJSON *index, cJSON *item)
{
    int ret = 0;
    cJSON *child = NULL;
    cJSON *result = NULL;
    uint8_t *renameStr = NULL;

    child = index->child;
    while (child != NULL)
    {
        if (cJSON_IsString(child)) // 要求为字符型
        {
            // attributeName_rename(child->string, &renameStr);  // 不用此方法
            // result = cJSON_GetObjectItemCaseSensitive(item, renameStr);
            result = cJSON_GetObjectItemCaseSensitive(item, child->string);
            if (result != NULL)
            {
                if (cJSON_IsString(result))
                {
                    if (!strcmp(result->string, "sdid")) // 需要处理返回的结果
                    {
                        uint8_t *p = result->valuestring + 20;
                        cJSON_SetValuestring(child, p);
                    }
                    else
                    {
                        cJSON_SetValuestring(child, result->valuestring);
                    }
                }
                else if (cJSON_IsNumber(result))
                {
                    uint8_t *p = format_string("%d", result->valueint);
                    cJSON_SetValuestring(child, p);
                    free(p);
                }
            }
            else
            {
                // 找不到跳过
            }
        }
        child = child->next;
    }
    return ERROR_NONE;
}

// 每两个字符转为一个数字
uint16_t little_endian_hex_to_int(const char *hex)
{
    uint16_t result = 0;
    int len = strlen(hex);
    uint8_t ch = 0;

    for (int i = len - 1; i >= 0; i--)
    {
        if (hex[i] >= '0' && hex[i] <= '9')
        {
            ch = hex[i] - '0';
        }
        else if (hex[i] >= 'a' && hex[i] <= 'f')
        {
            ch = hex[i] - 'a' + 10;
        }
        else if (hex[i] >= 'A' && hex[i] <= 'F')
        {
            ch = hex[i] - 'A' + 10;
        }
        if (i % 2 == 0)
        {
            result = (ch << 4) + result;
        }
        else
        {
            result = (result << 8) + ch;
        }
        // printf("%d\t", result);
    }

    return result;
}
// 具体函数接口
// 获取设备类型
/**
 * @description: 获取设备类型
 * @param {uint8_t} *id 传入设备id
 * @param {uint16_t} *deviceType 传出设备类型
 * @return {uint8_t} 返回0正常
 */
int list_getDeviceType(uint8_t *id, uint16_t *deviceType)
{
    int ret = 0;
    cJSON *deviceTypeJson = cJSON_CreateObject();
    cJSON_AddStringToObject(deviceTypeJson, "spid", "");
    printf("%s\n", id);
    cJSON *index = cJSON_CreateObject();
    cJSON_AddStringToObject(index, "sdid", id);
    ret = list_getOneAttrJson(devList_Json, index, &deviceTypeJson);
    // log_info("%s", cJSON_Print(deviceTypeJson));
    if (ret != ERROR_NONE)
    {
        return ret;
    }

    uint8_t ch[5] = {0}; // 小端05aa->0xaa05
    memcpy(ch, (deviceTypeJson->child->valuestring) + 24, 4);
    // sprintf(ch, "%s", "50ae");  //44624
    *deviceType = little_endian_hex_to_int(ch);
    printf("%s, %d\n", ch, *deviceType);
    // printf("%s, %s\n", deviceTypeJson->string, deviceTypeJson->valuestring);
    // printf("%s\n", cJSON_Print(item));
    return ERROR_NONE;
}

/**
 * @description: 获取设备短地址
 * @param {uint8_t} *id 设备ID
 * @param {uint16_t} *addr 返回的短地址结果
 * @return {*} 返回0执行正常，
 */
int list_getShortAddr(uint8_t *id, uint16_t *addr)
{
    int ret = 0;
    cJSON *addrJson = cJSON_CreateObject();
    cJSON_AddStringToObject(addrJson, "shortaddr", "");
    printf("%s\n", id);
    cJSON *index = cJSON_CreateObject();
    cJSON_AddStringToObject(index, "sdid", id);
    ret = list_getOneAttrJson(devList_Json, index, &addrJson);
    // log_info("%s", cJSON_Print(addrJson));
    if (ret != ERROR_NONE)
    {
        return ret;
    }

    *addr = atoi(addrJson->child->valuestring);
    printf("%d\n", *addr);
    return ERROR_NONE;
}

/**
 * @description: 查询数组内的属性是否需要上报数据
 * @param {uint8_t} *devID 设备ID
 * @param {cJSON} *json json数组
 * @return {*} 返回0需要上报，返回1不用上报
 */
int attributeNeedReport(uint8_t *devID, cJSON *json)
{
    int ret = 0;
    if (json == NULL)
    {
        return -1;
    }
    if (!cJSON_IsArray(json)) // 不是数组
    {
        return -1;
    }
    cJSON *element;
    cJSON_ArrayForEach(element, json) // element是含一个键值对的对象
    {
        cJSON *child = element->child; // 键值对
        // attributeName_rename(child->string, &serNameReplace);

        while (child != NULL) // 对象内多个键值对问题
        {
            for (int i = 0; i < attributeName_report_SIZE; i++)
            {
                if (!strcmp(child->string, attributeName_report[i]))
                {
                    ret = 0;
                    return ret;
                    // 存在需要查询的列表中
                }
            }
            child = child->next;
        }
    }
    return 1;
}
/**
 * @description: 填充需要上报数据的Json数据
 * @param {uint8_t} *devID 设备ID
 * @param {cJSON} *json 数组config
 * @return {*} 返回0成功，返回-1失败
 */
int checkReportJson(uint8_t *devID, cJSON *json)
{
    int ret = 0;
    if (json == NULL)
    {
        return -1;
    }
    if (!cJSON_IsArray(json)) // 不是数组
    {
        return -1;
    }

    ret = attributeNeedReport(devID, json);
    if (ret != 0)
    {
        log_info("无上报属性");
        return 0; // 没有需要上报数据的属性
    }
    // 需要上报数据流程
    // 查找短地址，发送查询，获取结果，查找设备类型，解析结果，赋值json
    uint16_t addr = 0;
    ret = list_getShortAddr(devID, &addr);
    if (ret != 0)
    {
        return -1;
    }
    ret = OneDevTriggerDataReport(addr); // 发送单个设备数据查询命令
    if (ret != 0)                        // 判断上一次查询是否结束
    {
        return -1;
    }
    ret = OneDevReportResult_wait(); // 设置同步并等待信号量
    if (ret != 0)
    {
        return -1;
    } // 结果在reportMsg_buffer，reportMsg_len

    uint16_t deviceType = 0;
    ret = list_getDeviceType(devID, &deviceType);
    if (ret != 0)
    {
        return -1;
    }

    log_info("设备类型");
    switch (deviceType) // 首先区分灯具类型
    {
    case 43051: // 色温灯0xa829(29 a8大端)
        /* code */
        light_status_json(reportMsg_buffer + 12, reportMsg_len - 12, json);
        break;
    case 43525: // 1开灯控面板 0xaa05(05 aa大端)
        switch_status_json(reportMsg_buffer + 12, reportMsg_len - 12, json);
        break;
    default:
        break;
    }

    char *msg = cJSON_Print(json);
    // printf("%s\n", msg);

    report_sem_post();
}

int controlDevJson(uint8_t *devID, cJSON *json)
{
    cJSON *config = json;
    // 查找设备类型
    uint16_t deviceType = 0;
    uint16_t addr = 0;
    log_debug("%s called\n", __func__);

    int16_t cf_on_off = -1;
    int16_t cf_bright = -1;
    int16_t cf_colorTemp = -1;
    // int16_t //RGB灯

    list_getDeviceType(devID, &deviceType);
    list_getShortAddr(devID, &addr);
    printf("%s\n", cJSON_Print(config));

    // 获取config的值
    int arraySize = cJSON_GetArraySize(config);
    for (int i = 0; i < arraySize; ++i)
    {
        cJSON *configObject = cJSON_GetArrayItem(config, i);

        // Extract values from the config object
        cJSON *_configObject = cJSON_GetObjectItem(configObject, "CF_OnOff");
        if (_configObject != NULL)
        {
            if (cJSON_IsNumber(_configObject))
            {
                cf_on_off = _configObject->valueint;
            }
            if (cJSON_IsString(_configObject))
            {
                cf_on_off = atoi(_configObject->valuestring);
            }
        }
        _configObject = cJSON_GetObjectItem(configObject, "CF_Bright");
        if (_configObject != NULL)
        {
            if (cJSON_IsNumber(_configObject))
            {
                cf_bright = _configObject->valueint;
            }
            if (cJSON_IsString(_configObject))
            {
                cf_bright = atoi(_configObject->valuestring);
            }
        }
        _configObject = cJSON_GetObjectItem(configObject, "CF_ColorTemp");
        if (_configObject != NULL)
        {
            if (cJSON_IsNumber(_configObject))
            {
                cf_colorTemp = _configObject->valueint;
            }
            if (cJSON_IsString(_configObject))
            {
                cf_colorTemp = atoi(_configObject->valuestring);
            }
        }

        switch (deviceType)
        {
        case 43051: // 色温灯
        case 43050: // RGB色温灯
            /* code */
            if ((cf_on_off == 0) || (cf_on_off == 1 && cf_on_off == -1 && cf_colorTemp == -1))
            {
                light_control_OnOff(addr, cf_on_off); // 只执行开关动作
            }
            else if (1)
            {
                if (cf_bright == -1)
                {
                    cf_bright = 100; // 默认最大亮度
                }
                if (cf_colorTemp == -1)
                {
                    cf_colorTemp = 127; // 默认中色温
                }
                light_control_Bright_ColorTemp(addr, cf_bright, 255 - cf_colorTemp, cf_colorTemp);
            }
            // light_control_Bright_ColorTemp
            break;
        case 43525: // 开关
            switch_control_OnOff(addr, cf_on_off);
        default:
            break;
        }
    }

    // if (_configObject != NULL)
    // {
    //     int cf_bright = 0;
    //     if (cJSON_IsNumber(_configObject))
    //     {
    //         cf_bright = _configObject->valueint;
    //     }
    //     if (cJSON_IsString(_configObject))
    //     {
    //         cf_bright = atoi(_configObject->valuestring);
    //     }
    //     light_control_Bright(addr, cf_bright);
    // }
}

// 群组控制对象为灯, 需要查找该群组的PID，并使用
int controlGroupJson(uint16_t groupID, cJSON *json)
{
    int ret = 0;
    uint8_t controlData[6] = {0};

    cJSON *config = json;
    uint16_t device_type = 0;

    int cf_on_off = -1;
    int cf_bright = -1;
    int cf_colorTemp = -1;
    int cf_r = -1;
    int cf_g = -1;
    int cf_b = -1;
    // 获取config的值
    int arraySize = cJSON_GetArraySize(config);
    for (int i = 0; i < arraySize; ++i)
    {
        cJSON *configObject = cJSON_GetArrayItem(config, i);

        // Extract values from the config object
        cJSON *_configObject = cJSON_GetObjectItem(configObject, "CF_OnOff");
        if (_configObject != NULL)
        {
            if (cJSON_IsNumber(_configObject))
            {
                cf_on_off = _configObject->valueint;
            }
            if (cJSON_IsString(_configObject))
            {
                cf_on_off = atoi(_configObject->valuestring);
            }
        }

        _configObject = cJSON_GetObjectItem(configObject, "CF_Bright");
        if (_configObject != NULL)
        {
            if (cJSON_IsNumber(_configObject))
            {
                cf_bright = _configObject->valueint;
            }
            if (cJSON_IsString(_configObject))
            {
                cf_bright = atoi(_configObject->valuestring);
            }
        }

        _configObject = cJSON_GetObjectItem(configObject, "CF_ColorTemp");
        if (_configObject != NULL)
        {
            if (cJSON_IsNumber(_configObject))
            {
                cf_colorTemp = _configObject->valueint;
            }
            if (cJSON_IsString(_configObject))
            {
                cf_colorTemp = atoi(_configObject->valuestring);
            }
        }

        _configObject = cJSON_GetObjectItem(configObject, "CF_R");
        if (_configObject != NULL)
        {
            if (cJSON_IsNumber(_configObject))
            {
                cf_r = _configObject->valueint;
            }
            if (cJSON_IsString(_configObject))
            {
                cf_r = atoi(_configObject->valuestring);
            }
        }

        _configObject = cJSON_GetObjectItem(configObject, "CF_G");
        if (_configObject != NULL)
        {
            if (cJSON_IsNumber(_configObject))
            {
                cf_g = _configObject->valueint;
            }
            if (cJSON_IsString(_configObject))
            {
                cf_g = atoi(_configObject->valuestring);
            }
        }

        _configObject = cJSON_GetObjectItem(configObject, "CF_B");
        if (_configObject != NULL)
        {
            if (cJSON_IsNumber(_configObject))
            {
                cf_b = _configObject->valueint;
            }
            if (cJSON_IsString(_configObject))
            {
                cf_b = atoi(_configObject->valuestring);
            }
        }
    }

    // device_type获取设备类型
    uint8_t ch[20] = {0};
    snprintf(ch, sizeof(ch), "%d", groupID);
    cJSON *index = NULL;
    index = cJSON_CreateObject();
    cJSON_AddStringToObject(index, "groupId", ch);
    cJSON *blecatetoryJson = NULL;
    blecatetoryJson = cJSON_CreateObject();
    cJSON_AddStringToObject(blecatetoryJson, "blecatetory", "");
    ret = list_getOneAttrJson(groupList_Json, index, &blecatetoryJson);
    if (ret != 0)
    {
        fprintf(stderr, "check group json failed\n");
    }
    memset(ch, 0, sizeof(ch));
    strncpy(ch, blecatetoryJson->child->valuestring, sizeof(ch));
    cJSON_Delete(index);
    cJSON_Delete(blecatetoryJson);
    if (!strcmp(ch, "CWLIGHT"))
    {
        device_type = 0x2ba8;
    }
    else if (!strcmp(ch, "RGBCWLIGHT"))
    {
        device_type = 0x2aa8;
    }
    else
    {
        device_type = 0x2ba8;
    }
    log_info("group test:%s", ch);
    log_info("group type:0X%X", device_type);
    // 只有开关一项
    if (cf_on_off != -1 &&
        cf_bright == -1 &&
        cf_colorTemp == -1 &&
        cf_r == -1 &&
        cf_g == -1 &&
        cf_b == -1)
    {
        controlData[0] = cf_on_off ? 0x80 : 0;
        ret = FastConbleGroupControl(groupID, device_type, controlData, 1);
    }
    else if (cf_on_off == 0)
    {
        controlData[0] = 0;
        ret = FastConbleGroupControl(groupID, device_type, controlData, 1);
    }
    else
    {
        if (cf_bright == -1)
        {
            cf_bright = 100; // 最大亮度
        }
        if (cf_colorTemp == -1)
        {
            cf_colorTemp = 127; // 冷暖一半色温
        }
        if (cf_r == -1)
        {
            cf_r = 0; // R
        }
        if (cf_g == -1)
        {
            cf_g = 0; // G
        }
        if (cf_b == -1)
        {
            cf_b = 0; // B
        }
        controlData[0] = (uint16_t)cf_bright * 127 / 100;
        if (cf_on_off)
        {
            controlData[0] |= 0x80;
        }
        controlData[1] = cf_b;
        controlData[2] = cf_r;
        controlData[3] = cf_g;
        controlData[4] = 255 - cf_colorTemp;
        controlData[5] = cf_colorTemp; // 冷光
        ret = FastConbleGroupControl(groupID, device_type, controlData, 6);
    }
}

// 房间控制对象为灯
int controlAllJson(uint16_t ID, cJSON *json)
{
    int ret = 0;
    uint32_t sceneID = 0; // 占用3个字节
    int cf_on_off = -1;

    ID = ID;

    cJSON *config = json;
    // 获取config的值
    int arraySize = cJSON_GetArraySize(config);
    for (int i = 0; i < arraySize; ++i) // 基本这里为1
    {
        cJSON *configObject = cJSON_GetArrayItem(config, i);

        // Extract values from the config object
        cJSON *_configObject = cJSON_GetObjectItem(configObject, "CF_OnOff");
        if (_configObject != NULL)
        {
            if (cJSON_IsNumber(_configObject))
            {
                cf_on_off = _configObject->valueint;
            }
            if (cJSON_IsString(_configObject))
            {
                cf_on_off = atoi(_configObject->valuestring);
            }
            break; // 结束for
        }
    }

    if (cf_on_off == -1)
    {
        return -1; // 出错
    }

    // 构建json
    cJSON *index = NULL;
    index = cJSON_CreateObject();
    cJSON_AddStringToObject(index, "room", "全屋");
    if (cf_on_off) // 查找相应房间的“全开”场景号
    {              // 两个属性查找
        cJSON_AddStringToObject(index, "name", "全开");
    }
    else // 查找相应房间的“全关”场景号
    {
        cJSON_AddStringToObject(index, "name", "全关");
    }
    // 构建josn完成
    cJSON *element = NULL;
    cJSON_ArrayForEach(element, sceneList_Json)
    {
        int _ret = 0;
        _ret = matchItemJson(index, element);
        if (_ret == 0) // 匹配成功
        {
            char *ch = NULL;
            ch = cJSON_GetObjectItemCaseSensitive(element, "moduleid")->valuestring;
            // printf("room control:%s\n", ch);
            sceneID = strtol(ch, NULL, 10);
            if (sceneID != 0)
            {
                _ret = FastConbleSceneControl(sceneID);
            }
        }
    }
    // printf("room control:%d\n", sceneID);
    if (sceneID != 0)
    {
        return 0;
    }
    else
    {
        return -1; // 出错
    }
}

// 房间控制对象为灯
int controlRoomJson(uint16_t roomID, cJSON *json)
{
    int ret = 0;
    uint32_t sceneID = 0; // 占用3个字节
    int cf_on_off = -1;

    cJSON *config = json;
    // 获取config的值
    int arraySize = cJSON_GetArraySize(config);
    for (int i = 0; i < arraySize; ++i) // 基本这里为1
    {
        cJSON *configObject = cJSON_GetArrayItem(config, i);

        // Extract values from the config object
        cJSON *_configObject = cJSON_GetObjectItem(configObject, "CF_OnOff");
        if (_configObject != NULL)
        {
            if (cJSON_IsNumber(_configObject))
            {
                cf_on_off = _configObject->valueint;
            }
            if (cJSON_IsString(_configObject))
            {
                cf_on_off = atoi(_configObject->valuestring);
            }
            break; // 结束for
        }
    }

    if (cf_on_off == -1)
    {
        return -1; // 出错
    }

    // 构建json
    cJSON *index = NULL;
    char ch[10] = {0};
    index = cJSON_CreateObject();
    snprintf(ch, sizeof(ch), "%d", roomID);
    cJSON_AddStringToObject(index, "roomId", ch);
    if (cf_on_off) // 查找相应房间的“全开”场景号
    {              // 两个属性查找
        cJSON_AddStringToObject(index, "name", "全开");
    }
    else // 查找相应房间的“全关”场景号
    {
        cJSON_AddStringToObject(index, "name", "全关");
    }
    // 构建josn完成
    cJSON *element = NULL;
    cJSON_ArrayForEach(element, sceneList_Json)
    {
        int _ret = 0;
        _ret = matchItemJson(index, element);
        if (_ret == 0) // 匹配成功
        {
            char *ch = NULL;
            ch = cJSON_GetObjectItemCaseSensitive(element, "moduleid")->valuestring;
            // printf("room control:%s\n", ch);
            sceneID = strtol(ch, NULL, 10);
            if (sceneID != 0)
            {
                _ret = FastConbleSceneControl(sceneID);
            }
        }
    }
    // printf("room control:%d\n", sceneID);
    if (sceneID != 0)
    {
        return 0;
    }
    else
    {
        return -1; // 出错
    }
}

int hz_list_device_get(char *id, cJSON *filter, cJSON *config)
{
    // 传入filter config为json数组
    int ret = 0;
    id = NULL;

    if (filter == NULL || config == NULL) // 传入参数检查
    {
        return ERROR_INVALID_PARAM;
    }

    cJSON *index = NULL;
    cJSON *element = NULL;
    cJSON *_config = NULL;
    uint16_t devCount = 0; // 设备数
    index = cJSON_GetArrayItem(filter, 0);
    _config = cJSON_GetArrayItem(config, 0);
    cJSON_ArrayForEach(element, devList_Json) // 设备列表内的对象
    {
        int _ret = 0;
        _ret = matchItemJson(index, element);
        if (_ret == 0) // 匹配成功
        {
            devCount++;
            if (devCount == 1) // 只有一个设备时，不用新增数组成员
            {
                updateItemJson(_config, element);
            }
            else
            {
                _config = cJSON_Duplicate(_config, 1); // 深度复制
                cJSON_AddItemToArray(config, _config);
                updateItemJson(_config, element);
            }
            // printf("%s\n", cJSON_Print(config));
        }
    }
    // printf("%s\n", cJSON_Print(config));
}

int hz_list_scene_get(char *id, cJSON *filter, cJSON *config)
{
    // 传入filter config为json数组
    int ret = 0;
    id = NULL;

    if (filter == NULL || config == NULL) // 传入参数检查
    {
        return ERROR_INVALID_PARAM;
    }

    cJSON *index = NULL;
    cJSON *element = NULL;
    cJSON *_config = NULL;
    uint16_t devCount = 0; // 设备数
    index = cJSON_GetArrayItem(filter, 0);
    _config = cJSON_GetArrayItem(config, 0);
    cJSON_ArrayForEach(element, sceneList_Json) // 设备列表内的对象
    {
        int _ret = 0;
        _ret = matchItemJson(index, element);
        if (_ret == 0) // 匹配成功
        {
            devCount++;
            if (devCount == 1) // 只有一个设备时，不用新增数组成员
            {
                updateItemJson(_config, element);
            }
            else
            {
                _config = cJSON_Duplicate(_config, 1); // 深度复制
                cJSON_AddItemToArray(config, _config);
                updateItemJson(_config, element);
            }
            // printf("%s\n", cJSON_Print(config));
        }
    }
    // printf("%s\n", cJSON_Print(config));
}

int hz_list_group_get(char *id, cJSON *filter, cJSON *config)
{
    // 传入filter config为json数组
    int ret = 0;
    id = NULL;

    if (filter == NULL || config == NULL) // 传入参数检查
    {
        return ERROR_INVALID_PARAM;
    }

    cJSON *index = NULL;
    cJSON *element = NULL;
    cJSON *_config = NULL;
    uint16_t devCount = 0; // 设备数
    index = cJSON_GetArrayItem(filter, 0);
    _config = cJSON_GetArrayItem(config, 0);
    cJSON_ArrayForEach(element, groupList_Json) // 设备列表内的对象
    {
        int _ret = 0;
        _ret = matchItemJson(index, element);
        if (_ret == 0) // 匹配成功
        {
            devCount++;
            if (devCount == 1) // 只有一个设备时，不用新增数组成员
            {
                updateItemJson(_config, element);
            }
            else
            {
                _config = cJSON_Duplicate(_config, 1); // 深度复制
                cJSON_AddItemToArray(config, _config);
                updateItemJson(_config, element);
            }
            // printf("%s\n", cJSON_Print(config));
        }
    }
    // printf("%s\n", cJSON_Print(config));
}

int hz_list_room_get(char *id, cJSON *filter, cJSON *config)
{
    // 传入filter config为json数组
    int ret = 0;
    id = NULL;

    if (filter == NULL || config == NULL) // 传入参数检查
    {
        return ERROR_INVALID_PARAM;
    }

    cJSON *index = NULL;
    cJSON *element = NULL;
    cJSON *_config = NULL;
    uint16_t devCount = 0; // 设备数
    index = cJSON_GetArrayItem(filter, 0);
    _config = cJSON_GetArrayItem(config, 0);
    cJSON_ArrayForEach(element, roomList_Json) // 设备列表内的对象
    {
        int _ret = 0;
        // _ret = matchItemJson(index, element);
        // 默认为全部
        if (_ret == 0) // 匹配成功
        {
            devCount++;
            if (devCount == 1) // 只有一个设备时，不用新增数组成员
            {
                updateItemJson(_config, element);
            }
            else
            {
                _config = cJSON_Duplicate(_config, 1); // 深度复制
                cJSON_AddItemToArray(config, _config);
                updateItemJson(_config, element);
            }
            // printf("%s\n", cJSON_Print(config));
        }
    }
    // printf("%s\n", cJSON_Print(config));
}